﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Numbers.Arithmatic;
using System.ComponentModel;
using System.Collections.ObjectModel;

namespace Numbers
{
    /// <summary>
    /// Represents a single flavor sample
    /// </summary>
    public class FlavorSample : INotifyPropertyChanged
    {
        /// <summary>
        /// Create the flavor sample, and configure the relationships.
        /// </summary>
        public FlavorSample()
        {
            Addition.Create(_lightcharm, new Value[] { _light, _charm });
            Addition.Create(_total, new Value[] { _light, _charm, _bottom });

            ///
            /// When things change behind our backs, we need to notify folks! Hook up some forwarding stuff
            /// 

            _total.PropertyChanged += new PropertyChangedEventHandler((o, e) => { OnPropertyChanged("Total"); });
            _lightcharm.PropertyChanged += new PropertyChangedEventHandler((o, e) => { OnPropertyChanged("LightCharm"); });
            _light.PropertyChanged += new PropertyChangedEventHandler((o, e) => { OnPropertyChanged("Light"); });
            _charm.PropertyChanged += new PropertyChangedEventHandler((o, e) => { OnPropertyChanged("Charm"); });
            _bottom.PropertyChanged += new PropertyChangedEventHandler((o, e) => { OnPropertyChanged("Bottom"); });

            ///
            /// Setup the jet fraction dude!
            /// 

            JetbclFractions = new ObservableCollection<ValueTracker>();
            JetbclFractions.Add(new ValueTracker(_bottom) { Name = "b" });
            JetbclFractions.Add(new ValueTracker(_charm) { Name = "c" });
            JetbclFractions.Add(new ValueTracker(_light) { Name = "l" });
        }

        internal Value _total = new Value();
        internal Value _lightcharm = new Value();
        internal Value _light = new Value();
        internal Value _charm = new Value();
        internal Value _bottom = new Value();

        public Value TotalValue { get { return _total; } }
        public Value LightCharmValue { get { return _lightcharm; } }
        public Value LightValue { get { return _light; } }
        public Value CharmValue { get { return _charm; } }
        public Value BottomValue { get { return _bottom; } }

        public double Total { get { return _total.Val; } set { ChangeValue(ref _total, value, "Total"); } }

        public double Light { get { return _light.Val; } set { ChangeValue(ref _light, value, "Light"); } }

        public double Charm { get { return _charm.Val; } set { ChangeValue(ref _charm, value, "Charm"); } }

        public double Bottom { get { return _bottom.Val; } set { ChangeValue(ref _bottom, value, "Bottom"); } }

        public double LightCharm { get { return _lightcharm.Val; } set { ChangeValue(ref _lightcharm, value, "LightCharm"); } }

        /// <summary>
        /// When something changes, make it changed and then fire off an event!
        /// </summary>
        /// <param name="_total"></param>
        /// <param name="value"></param>
        /// <param name="p"></param>
        private void ChangeValue(ref Value v, double newValue, string propName)
        {
            if (v.Val != newValue)
            {
                v.Val = newValue;
            }
        }

        /// <summary>
        /// Fire off the property changed event as lon as someone is listening.
        /// </summary>
        /// <param name="propName"></param>
        private void OnPropertyChanged(string propName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propName));
            }
        }

        /// <summary>
        /// Multiply a sample times a tagging efficiency.
        /// </summary>
        /// <param name="p"></param>
        /// <param name="eff_away"></param>
        /// <param name="n"></param>
        public static void Multiply(FlavorSample result, TagEfficiency eff, FlavorSample source)
        {
            Multiplication.Create(new Operand(result._bottom), new Operand[] {
                new Operand(eff._eff_b),
                new Operand(source._bottom, true)
            });
            Multiplication.Create(new Operand(result._charm), new Operand[] {
                new Operand(eff._eff_c),
                new Operand(source._charm, true)
            });
            Multiplication.Create(new Operand(result._light), new Operand[] {
                new Operand(eff._eff_l),
                new Operand(source._light, true)
            });
        }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

        /// <summary>
        /// Returns an updating/tracking collection of the various
        /// fractions for b, c, and l.
        /// </summary>
        public ObservableCollection<ValueTracker> JetbclFractions { get; set; }

    }
}
